package com.zdsx.service.impl;

import cn.hutool.core.io.checksum.CRC16;
import com.zdsx.service.WxSystemService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.zip.Checksum;

import static org.junit.jupiter.api.Assertions.*;

//@SpringBootTest
class HexTest1 {

//    @Resource
    private WxSystemService wxSystemService;

    @Test
    void getOpenId() {
    }

    @Test
    void sendVerifySms() {
        wxSystemService.sendVerifySms("18670034144", new String[]{"1234", "5"});
    }

    /**
     *
     */



    @Test
    void testCodingHex() {
        // 示例输入
        byte serviceCode = 0x01; // 产品编码
        byte commandType = 0x11; // 功能类型
        byte executionResult = 0x01; // 执行结果
        String hexBody = ""; // 报文体内容的16进制表示，长度必须要是偶数

        // 转换为字节数组
        byte[] body = hexStringToByteArray(hexBody);

        // 生成报文
        String hexMessage = generateMessage(serviceCode, commandType, executionResult, body);

        // 输出报文
        System.out.println(hexMessage);

        // 解码报文
        decodeMessage(hexMessage);
    }

    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    public static String generateMessage(byte serviceCode, byte commandType, byte executionResult, byte[] body) {
        // 计算报文长度（包括起始符、长度字段、版本号、业务编码、指令类型、执行结果、报文体长度、报文体、校验码和结束符）
        int totalLength = 1 // 起始符
                + 2 // 长度字段（短整型，2字节）
                + 1 // 版本号
                + 1 // 业务编码
                + 1 // 指令类型
                + 1 // 执行结果
                + 2 // 报文体长度（短整型，2字节）
                + body.length // 报文体
                + 2 // 校验码（短整型，2字节）
                + 1; // 结束符

        // 初始化ByteBuffer
        ByteBuffer buffer = ByteBuffer.allocate(totalLength).order(ByteOrder.LITTLE_ENDIAN);

        // 添加起始符
        buffer.put((byte) 0x80);

        // 添加报文长度（跳过两个字节，稍后填充）
        buffer.position(buffer.position() + 2);

        // 添加版本号、业务编码、指令类型、执行结果
        buffer.put((byte) 0x01);
        buffer.put(serviceCode);
        buffer.put(commandType);
        buffer.put(executionResult);

        // 添加报文体长度
        buffer.putShort((short) body.length);

        // 添加报文体
        buffer.put(body);

        // 回到起始位置计算CRC16校验码（不包括起始符和长度字段，但包括结束符的位置）
        buffer.flip();
        byte[] temp = new byte[buffer.limit()];
        buffer.get(temp);
        buffer.clear(); // 清除缓冲区以便重新写入

        // 填充起始符和长度字段
        buffer.put((byte) 0x80);
        buffer.putShort((short) (totalLength - 2)); // 报文长度（不包括起始符和结束符）

        // 复制之前的内容（版本号到报文体）
        buffer.put(temp, 1, temp.length - 3); // 跳过长度字段，包括结束符的位置

        // 计算CRC16校验码（不包括起始符和结束符）
        Checksum crc16 = new CRC16();
        crc16.update(temp, 1, temp.length - 3); // 跳过长度字段，不包括结束符
        short crcValue = (short) crc16.getValue();

        // 填充校验码和结束符
        buffer.putShort(crcValue);
        buffer.put((byte) 0x81);

        // 转换为16进制字符串
        StringBuilder hex = new StringBuilder();
        for (byte b : buffer.array()) {
            hex.append(String.format("%02x", b));
        }

        return hex.toString();
    }



    public static void decodeMessage(String hexString) {
        // 将16进制字符串转换为字节数组
        byte[] bytes = hexStringToByteArray1(hexString);

        // 创建一个ByteBuffer来读取数据
        ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);

        // 验证起始符
        byte startByte = buffer.get();
        if (startByte != 0x80) {
            System.out.println("Invalid start byte: " + startByte);
            return;
        }

        // 读取长度字段
        short length = buffer.getShort();
        System.out.println("Length field: " + length);

        // 读取版本号、业务编码、指令类型、执行结果
        byte version = buffer.get();
        byte businessCode = buffer.get();
        byte commandType = buffer.get();
        byte executionResult = buffer.get();
        System.out.println("Version: " + (version & 0xFF));
        System.out.println("Business Code: " + (businessCode & 0xFF));
        System.out.println("Command Type: " + (commandType & 0xFF));
        System.out.println("Execution Result: " + (executionResult & 0xFF));

        // 读取报文体长度字段
        short bodyLength = buffer.getShort();
        System.out.println("Body length: " + bodyLength);

        // 读取报文体
        byte[] body = new byte[bodyLength];
        buffer.get(body);
        // 可以将报文体转换为字符串（如果它是文本数据）或其他格式
        // 这里我们仅打印数组长度
        System.out.println("Body (length): " + body.length);

        // 读取CRC16校验码
        short crc16 = buffer.getShort();
        System.out.println("CRC16: " + crc16);

        // 验证结束符
        byte endByte = buffer.get();
        if (endByte != 0x81) {
            System.out.println("Invalid end byte: " + endByte);
            return;
        }

        // 一切正常，打印结束信息
        System.out.println("Message decoded successfully.");
    }

    private static byte[] hexStringToByteArray1(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
}